﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;

namespace Microsoft.ProductivityHub.SilverlightBookshelf
{
    public class SharePointData : UserControl
    {
        
        private ListItemCollection _listItems = null;
        private const string _docLibName = "Content Library";
        private string _currentWebUrl = null;

        private SharePoint.Client.User _currentUser = null;

        public delegate void DataLoaded(System.Collections.Generic.List<ContentItem> contentItems);
        public event DataLoaded DataLoadedEvent;

        private delegate void UserLoaded(SharePoint.Client.User currentUser);
        private event UserLoaded UserLoadedEvent;

        private const string _featuredContentItemsCamlQuery = @"<View>
                <Query>
                  <OrderBy><FieldRef Name='Title' Ascending='TRUE'/></OrderBy>
                  <Where>
                       <Eq><FieldRef Name='IsFeaturedContent'/><Value Type='Boolean'>1</Value></Eq>
                  </Where>
                </Query>
                <RowLimit>100</RowLimit>
              </View>";

        private string _topRatedItemsCamlQuery = @"<View>
                <Query>
                    <OrderBy>
                    <FieldRef Name='AverageRating' Ascending='FALSE'/>
                    <FieldRef Name='Title' Ascending='TRUE'/>
                    </OrderBy>
                  <Where>
                       <Gt><FieldRef Name='AverageRating'/><Value Type='Counter'>3</Value></Gt>
                  </Where>
                </Query>
                <RowLimit>20</RowLimit>
              </View>";

        private string _featuredVideoItemsCamlQuery = @"<View>
                <Query>
                  <OrderBy><FieldRef Name='Modified' Ascending='FALSE'/></OrderBy>
                  <Where>
                    <And>
                       <Eq><FieldRef Name='IsVideoContent'/><Value Type='Boolean'>1</Value></Eq>
                       <Eq><FieldRef Name='AppearsInRotator'/><Value Type='Boolean'>1</Value></Eq>
                    </And>
                  </Where>
                </Query>
                <RowLimit>900</RowLimit>
              </View>";

        public string CurrentWebUrl
        {
            get
            {
                if (String.IsNullOrEmpty(_currentWebUrl))
                {
                    _currentWebUrl = ApplicationContext.Current.Url;
                }
                return _currentWebUrl;
            }
        }

        /// <summary>
        /// Generic internal query items for Featured Content and Top Rated
        /// </summary>
        /// <param name="camlQuery"></param>
        private void QueryItems(string camlQueryString)
        {
            ClientRequestSucceededEventHandler onSuccess = new ClientRequestSucceededEventHandler(OnSucceeded);
            ClientRequestFailedEventHandler onFailure = new ClientRequestFailedEventHandler(OnFailed);

            Microsoft.SharePoint.Client.ClientContext cc = new Microsoft.SharePoint.Client.ClientContext(this.CurrentWebUrl);

            List list = cc.Web.Lists.GetByTitle("Content Library");

            CamlQuery camlQuery = new CamlQuery();
            camlQuery.ViewXml = camlQueryString;

            _listItems = list.GetItems(camlQuery);

            cc.Load(_listItems,
                 items => items
                     .Include(
                         item => item["ID"],
                         item => item["Title"],
                         item => item["DocIcon"],
                         item => item["Abstract"],
                         item => item["RatingCount"],
                         item => item["AverageRating"],
                         item => item["ThumbnailImageUrl"],
                         item => item["Difficulty"],
                         item => item["Product"],
                         item => item["Modified"],
                         item => item["FileLeafRef"],
                         item => item["FileRef"]));

            cc.ExecuteQueryAsync(onSuccess, onFailure);

        }


        public void QueryFeaturedContentItems()
        {
            QueryItems(_featuredContentItemsCamlQuery);
        }

        private string GetAbsoluteUrlForIcon(string docIcon)
        {
            string tempUrl = _currentWebUrl.TrimEnd('/');
            if (String.IsNullOrEmpty(docIcon))
            {
                return string.Format("{0}/_layouts/images/icgen.gif", tempUrl);
            }
            else
            {
                return string.Format("{0}/_layouts/images/ic{1}.gif", tempUrl, docIcon);
                // return string.Format("{0}/_layouts/images/icdot.png", tempUrl);
            }
        }

        private string GetLocalUrlForIcon(string docIcon)
        {
            if (!String.IsNullOrEmpty(docIcon) && App.SupportedIconNames.Contains(docIcon.ToUpper()))
            {
                return string.Format("../Images/Icons/ic{0}.png", docIcon);
                // return string.Format("{0}/_layouts/images/icdot.png", tempUrl);
            }
            else
            {
                return "../Images/Icons/icgen.png";
            }
        }


        private string GetAbsoluteUrlForContent(string filename)
        {
            if (String.IsNullOrEmpty(filename))
            {
                filename = "notfound.html";
            }
            string tempUrl = _currentWebUrl.TrimEnd('/');
            return string.Format("{0}/ContentLibrary/{1}", tempUrl, filename);
        }


        private void OnFailed(object sender, Microsoft.SharePoint.Client.ClientRequestFailedEventArgs e)
        {
            throw new Exception(e.Message + " " + e.ErrorDetails);
        }


        private void OnSucceeded(object sender, Microsoft.SharePoint.Client.ClientRequestSucceededEventArgs e)
        {
            // Data operations occur here
            if (_listItems != null && _listItems.Count > 0)
            {
                System.Collections.Generic.List<ContentItem> contentItems = new System.Collections.Generic.List<ContentItem>(_listItems.Count);

                // Create a VideoItem object for each list item in the list
                foreach (ListItem listItem in _listItems)
                {
                    ContentItem contentItem = new ContentItem();
                    contentItem.DocId = listItem["ID"].ToString();
                    contentItem.Abstract = (string)listItem["Abstract"];
                    contentItem.Difficulty = (string)listItem["Difficulty"];
                    contentItem.Title = (string)listItem["Title"];
                    contentItem.Product = ((Microsoft.SharePoint.Client.FieldLookupValue)listItem["Product"]).LookupValue;
                    contentItem.DocUrl = GetAbsoluteUrlForContent((string)listItem["FileLeafRef"]);
                    contentItem.IconUrl = GetLocalUrlForIcon((string)listItem["DocIcon"]);
                    if (listItem["RatingCount"] != null)
                    {
                        contentItem.NumberOfRatings = Int32.Parse(listItem["RatingCount"].ToString());
                    }
                    else
                    {
                        contentItem.NumberOfRatings = 0;
                    }

                    if (listItem["AverageRating"] != null)
                    {
                        double tempAvgRating = Double.Parse(listItem["AverageRating"].ToString());
                        contentItem.RatingValue = (tempAvgRating / 5);
                    }
                    else
                    {
                        contentItem.RatingValue = 0;
                    }

                    contentItems.Add(contentItem);

                }
                // _Loaded.Invoke(videos); // this performs the invoke on the non-UI thread
                this.Dispatcher.BeginInvoke(DataLoadedEvent, contentItems); // this performs the invoke on the UI thread
                //Dispatcher.BeginInvoke(() => { MessageBox.Show(webHub.CurrentUser.LoginName); });
            }
            else
            {
                this.Dispatcher.BeginInvoke(DataLoadedEvent, new System.Collections.Generic.List<ContentItem>()); // this performs the invoke on the UI thread
            }

        }


        private void OnFeaturedVideoSucceeded(object sender, Microsoft.SharePoint.Client.ClientRequestSucceededEventArgs e)
        {
            // Data operations occur here
            if (_listItems != null && _listItems.Count > 0)
            {
                int randomIndex = new Random().Next(_listItems.Count);
                System.Collections.Generic.List<ContentItem> _contentItems = new System.Collections.Generic.List<ContentItem>(1);

                // Create a ContentItem object for the single randomly selected listitem
                ListItem listItem = _listItems[randomIndex];

                ContentItem contentItem = new ContentItem();
                contentItem.DocId = listItem["ID"].ToString();
                contentItem.Abstract = (string)listItem["Abstract"];
                contentItem.Difficulty = (string)listItem["Difficulty"];
                contentItem.Title = (string)listItem["Title"];
                contentItem.Product = ((Microsoft.SharePoint.Client.FieldLookupValue)listItem["Product"]).LookupValue;
                contentItem.DocUrl = GetAbsoluteUrlForContent((string)listItem["FileLeafRef"]);
                contentItem.IconUrl = GetAbsoluteUrlForIcon((string)listItem["DocIcon"]);
                if (listItem["RatingCount"] != null)
                {
                    contentItem.NumberOfRatings = Int32.Parse(listItem["RatingCount"].ToString());
                }
                else
                {
                    contentItem.NumberOfRatings = 0;
                }

                if (listItem["AverageRating"] != null)
                {
                    double tempAvgRating = Double.Parse(listItem["AverageRating"].ToString());
                    contentItem.RatingValue = (tempAvgRating / 5);
                }
                else
                {
                    contentItem.RatingValue = 0;
                }

                _contentItems.Add(contentItem);

                // _Loaded.Invoke(videos); // this performs the invoke on the non-UI thread
                this.Dispatcher.BeginInvoke(DataLoadedEvent, _contentItems); // this performs the invoke on the UI thread
                //Dispatcher.BeginInvoke(() => { MessageBox.Show(webHub.CurrentUser.LoginName); });
            }
            else
            {
                this.Dispatcher.BeginInvoke(DataLoadedEvent, new System.Collections.Generic.List<ContentItem>()); // this performs the invoke on the UI thread
            }

        }

        public void QueryFeaturedVideo()
        {
            ClientRequestSucceededEventHandler onSuccess = new ClientRequestSucceededEventHandler(OnFeaturedVideoSucceeded);
            ClientRequestFailedEventHandler onFailure = new ClientRequestFailedEventHandler(OnFailed);

            Microsoft.SharePoint.Client.ClientContext cc = new Microsoft.SharePoint.Client.ClientContext(this.CurrentWebUrl);

            List list = cc.Web.Lists.GetByTitle("Content Library");

            CamlQuery camlQuery = new CamlQuery();
            camlQuery.ViewXml = _featuredVideoItemsCamlQuery;

            _listItems = list.GetItems(camlQuery);

            cc.Load(_listItems,
                 items => items
                     .Include(
                         item => item["ID"],
                         item => item["Title"],
                         item => item["DocIcon"],
                         item => item["Abstract"],
                         item => item["RatingCount"],
                         item => item["AverageRating"],
                         item => item["ThumbnailImageUrl"],
                         item => item["Difficulty"],
                         item => item["Product"],
                         item => item["Modified"],
                         item => item["FileLeafRef"],
                         item => item["FileRef"]));

            cc.ExecuteQueryAsync(onSuccess, onFailure);
        }


        public void QueryTopRatedItems()
        {
            QueryItems(_topRatedItemsCamlQuery);
        }


        // Function related to Favorites query
        private void OnGetUserSuccess(object sender, Microsoft.SharePoint.Client.ClientRequestSucceededEventArgs e)
        {
            this.Dispatcher.BeginInvoke(UserLoadedEvent, _currentUser); // this performs the invoke on the UI thread
        }

        // Function related to Favorites query
        private void QueryCurrentUser()
        {
            try
            {
                if (_currentUser == null)
                {
                    ClientRequestSucceededEventHandler onGetUserSuccess = new ClientRequestSucceededEventHandler(OnGetUserSuccess);
                    ClientRequestFailedEventHandler onFailure = new ClientRequestFailedEventHandler(OnFailed);

                    Microsoft.SharePoint.Client.ClientContext cc = new Microsoft.SharePoint.Client.ClientContext(this.CurrentWebUrl);
                    _currentUser = cc.Web.CurrentUser;
                    cc.Load(_currentUser, ccuser => ccuser.LoginName);
                    cc.ExecuteQueryAsync(onGetUserSuccess, onFailure);
                }
                else
                {
                    // we already have the _currentUser, execute the UserLoadedEvent directly
                    this.Dispatcher.BeginInvoke(UserLoadedEvent, _currentUser); // this performs the invoke on the UI thread
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message + " " + err.StackTrace);
            }
        }

        // Function related to Favorites query
        private void SharePointData_UserLoadedEvent(User currentUser)
        {
            if (currentUser != null)
            {
                // only return favorites if the current user is not null
                string jsFunction = "hub2010_FetchFavoritesXmlForSilverlight";
                // string jsFunction = "hub2010_Test";
                string result = (string)System.Windows.Browser.HtmlPage.Window.Invoke(jsFunction, new object[] { currentUser.LoginName });
                // MessageBox.Show(result);

                System.IO.StringReader stream = new System.IO.StringReader(result);
                System.Xml.XmlReader reader = System.Xml.XmlReader.Create(stream);

                // <Favorites>/<Favorite>/<Url>[urlvalue]</Url><Title>[titlevalue]</Title>
                List<ContentItem> favoriteItems = new List<ContentItem>();

                while (reader.Read())
                {
                    if (reader.NodeType == System.Xml.XmlNodeType.Element)
                    {
                        if (reader.Name == "Favorite")
                        {
                            favoriteItems.Add(ParseFavoriteItem(reader.ReadSubtree()));
                        }
                    }
                }

                favoriteItems.Sort();
                this.Dispatcher.BeginInvoke(DataLoadedEvent, favoriteItems); // this performs the invoke on the UI thread
            }

        }


        /// <summary>
        /// Queries the list of content items based on the javasccript function "FetchFavoritesXmlForSilverlight"
        /// </summary>
        /// <returns></returns>
        public void QueryFavorites()
        {
            // to query for favorites, we need to query for the current User
            this.UserLoadedEvent += new UserLoaded(SharePointData_UserLoadedEvent);
            QueryCurrentUser();
        }

        // Function related to Favorites query
        private ContentItem ParseFavoriteItem(System.Xml.XmlReader subtree)
        {
            ContentItem ci = new ContentItem();
            if (subtree != null)
            {
                while (subtree.Read())
                {
                    if (subtree.Name == "Url")
                    {
                        ci.DocUrl = subtree.ReadInnerXml();
                    }
                    if (subtree.Name == "Title")
                    {
                        ci.Title = subtree.ReadInnerXml();
                    }
                }
            }
            return ci;

        }
    }
}
